import pyaudio
import time
import queue

# 录音模块：处理音频录制

# 默认音频配置
DEFAULT_FORMAT = pyaudio.paInt16
DEFAULT_CHANNELS = 1
DEFAULT_RATE = 16000
CHUNK_SIZE = 960

# 录音队列
RECORDING_QUEUE = queue.Queue(maxsize=500)

class AudioRecorder:
    def __init__(self, recording_queue=None):
        self.recording_queue = recording_queue or RECORDING_QUEUE
        self.is_recording_active = False
    
    # 录音任务
    async def record_audio(self, is_recording_flag):
        p = None
        stream = None
        consecutive_errors = 0
        max_consecutive_errors = 3
        device_available = False
        
        try:
            # 初始化PyAudio
            p = pyaudio.PyAudio()
            
            # 获取默认输入设备
            try:
                default_device_index = int(p.get_default_input_device_info()['index'])  # type: ignore
                device_info = p.get_device_info_by_index(default_device_index)
                print(f"[RECORD] 使用默认输入设备: {device_info['name']}")
                device_available = True
            except Exception as device_e:
                print(f"[WARN] 无法获取默认录音设备信息: {device_e}")
                print(f"[INFO] 录音功能将不可用，但程序将继续运行")
                device_available = False
            
            # 只有当设备可用时才尝试打开流
            if device_available:
                try:
                    # 打开音频输入流
                    stream = p.open(
                        format=DEFAULT_FORMAT,
                        channels=DEFAULT_CHANNELS,
                        rate=DEFAULT_RATE,
                        input=True,
                        frames_per_buffer=CHUNK_SIZE
                    )
                    print(f"[RECORD] 录音流已创建 - {DEFAULT_RATE}Hz, {DEFAULT_CHANNELS}声道, {CHUNK_SIZE}采样点/帧")
                except Exception as stream_e:
                    print(f"[ERROR] 无法打开录音流: {stream_e}")
                    print(f"[INFO] 录音功能将不可用，但程序将继续运行")
                    device_available = False
            
            # 录音循环
            while True:
                try:
                    # 检查是否需要录音且设备可用
                    if is_recording_flag() and device_available and stream is not None:
                        self.is_recording_active = True
                        # 读取音频数据
                        data = stream.read(CHUNK_SIZE, exception_on_overflow=False)
                        
                        # 将录音数据放入队列
                        try:
                            # 使用阻塞式put，带超时
                            self.recording_queue.put(data, timeout=0.1)
                            
                            # 定期打印队列状态
                            queue_size = self.recording_queue.qsize()
                            if queue_size % 10 == 0:
                                print(f"[RECORD] 录音队列状态: {queue_size}/{self.recording_queue.maxsize}")
                        except queue.Full:
                            # 队列满时，尝试清理一个位置
                            try:
                                # 清理一个旧数据块，保存新数据
                                self.recording_queue.get_nowait()
                                self.recording_queue.task_done()
                                self.recording_queue.put_nowait(data)
                                print(f"[RECORD] 录音队列已满，已清理一个旧数据块")
                            except:
                                print(f"[ERROR] 录音队列已满且无法清理，丢弃当前数据块")
                    else:
                        self.is_recording_active = False
                        # 不录音时，短暂休眠以减少CPU使用
                        await asyncio.sleep(0.1)
                    
                    # 重置错误计数
                    consecutive_errors = 0
                    
                except Exception as e:
                    consecutive_errors += 1
                    
                    if consecutive_errors >= max_consecutive_errors:
                        print(f"[ERROR] 连续 {max_consecutive_errors} 次录音错误: {e}")
                        if device_available and stream is not None:
                            print(f"[INFO] 尝试重新初始化录音设备")
                            # 重新初始化音频设备
                            try:
                                stream.stop_stream()
                                stream.close()
                            except:
                                pass
                            
                            try:
                                stream = p.open(
                                    format=DEFAULT_FORMAT,
                                    channels=DEFAULT_CHANNELS,
                                    rate=DEFAULT_RATE,
                                    input=True,
                                    frames_per_buffer=CHUNK_SIZE
                                )
                                print("[RECORD] 录音设备已重新初始化")
                                consecutive_errors = 0
                            except Exception as init_e:
                                print(f"[ERROR] 重新初始化录音设备失败: {init_e}")
                                print(f"[INFO] 录音功能将被禁用")
                                device_available = False
                                stream = None
                        consecutive_errors = 0  # 重置计数器
                    
                    # 短暂休眠以避免CPU占用过高
                    await asyncio.sleep(0.1)
        
        except Exception as e:
            print(f"[WARN] 录音任务初始化失败: {e}")
            print(f"[INFO] 录音功能不可用，但程序将继续运行")
            # 不抛出异常，让任务继续运行但什么都不做
            while True:
                await asyncio.sleep(1)
        finally:
            # 确保资源被释放
            print("[RECORD] 录音任务结束，释放资源")
            self.is_recording_active = False
            
            try:
                if stream is not None:
                    stream.stop_stream()
                    stream.close()
                if p is not None:
                    p.terminate()
            except:
                pass
    
    # 清空录音队列
    def clear_recording_queue(self):
        if not self.recording_queue.empty():
            cleared_count = 0
            while not self.recording_queue.empty():
                try:
                    self.recording_queue.get_nowait()
                    self.recording_queue.task_done()
                    cleared_count += 1
                except queue.Empty:
                    break
            print(f"[RECORD] 已清空录音队列中的 {cleared_count} 个数据块")
        else:
            print("录音队列为空，无需清理")
    
    # 获取当前队列状态
    def get_queue_status(self):
        return {
            'size': self.recording_queue.qsize(),
            'maxsize': self.recording_queue.maxsize,
            'is_full': self.recording_queue.full()
        }
    
    # 获取录音状态
    def get_recording_state(self):
        return self.is_recording_active

# 需要导入asyncio
import asyncio